/**
 * 
 */
package it.unical.canonaco.rende.igpe.game.cbv.guilayer.components;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import it.unical.canonaco.rende.igpe.game.cbv.guilayer.match.MatchPanel;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.MatchManager;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.MatchOnLineManager;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions.ActionCoordinateInfo;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions.ActionMediator;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions.AddCharacterInfo;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.actions.StartingPointAction;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.pawn.Character;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.player.BattlePlayer;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.player.SimplePlayer;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.world.Chessboard;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.world.Map;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.netgame.BoomerangProtocol;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.netgame.OnLineEnemyController;

/**
 * @author Massimo Canonaco
 *
 */
public class SyncHandlerMOLM 
{
	/** */
	private Map map;
	
	private Lock lock;
	private Condition condition;
	
	private boolean mapOff;
	private boolean enemyOff;
	
	public SyncHandlerMOLM()
	{
		lock = new ReentrantLock();
		condition = lock.newCondition();
		
		mapOff = true;
		enemyOff = true;
	}
	public void initMatch(BoomerangProtocol protocol, MatchOnLineManager matchManager) throws UnknownHostException, IOException 
	{
		// Check if you're the server.
		if(protocol.isYouAreServerNow())
		{
			// Server must set the starting position.
			// Get players and get arena.
			BattlePlayer playerOne = matchManager.getClientPlayer(), playerTwo = matchManager.getEnemy();
			Chessboard arena = matchManager.getMap().getArena();

			System.out.println("HAI "+playerOne.getCharacters().size());
			// Place the server characters.
			matchManager.placeWarriors(playerOne.getActions(), playerOne.getCharacters(), arena);
			
			System.out.println("HA "+playerTwo.getCharacters().size());
			// Place the remote characters.
			matchManager.placeWarriors(playerTwo.getActions(), playerTwo.getCharacters(), arena);

			// Setting the index of the player who's going to play the first turn.
//			int random = ((new Random(2)).nextInt())%2;
			matchManager.setStartingPlayerIndex(((new Random()).nextInt(2)));
			
//			System.out.println("IL GIOCATORE CHE INIZIA IL TURNO E : "+matchManager.getStartingPlayerIndex());
			// Send all the informations.
			sedingActions(protocol,matchManager);
			
			// Waiting for the "remote side"
			protocol.receiveMessage();
			
			
		}
		// You're not the server.
		else
		{
			// Receive the informations and set up your "matchManager".
			recevingActions(protocol, matchManager);
			
			// Signal to server your configuration is ok.
			protocol.sendMessage("");
		}
	}

	private void recevingActions(BoomerangProtocol protocol, MatchOnLineManager matchManager) throws UnknownHostException, IOException 
	{
		String a = protocol.receiveMessage();
		System.out.println("ricevuto: "+a);
		int startingPlayerIndex = Integer.parseInt(a);
		matchManager.setStartingPlayerIndex(startingPlayerIndex);
		
		List<Character> players = matchManager.getEnemy().getCharacters();
		ActionMediator mediator = matchManager.getEnemy().getActions();
		// For each players we're going to receive his name and his position.
		// Receive server players (the enemy).
		String name = null;
		int row = -1, column = -1, size = players.size();
		
		for(int index = 0; index < size; index++)
		{
			// Name
			name = protocol.receiveMessage();
			
			// Row
			row = Integer.parseInt(protocol.receiveMessage());
			
			// Column
			column = Integer.parseInt(protocol.receiveMessage());
			for (Character character : players) 
			{
				if(name.equalsIgnoreCase(character.getName()))
				{
					System.out.println("imposto posizione per "+name+" in "+row+" "+column);
					mediator.setAction(StartingPointAction.GUID);
					mediator.addActionInfo(new AddCharacterInfo(character));
					mediator.addActionInfo(new ActionCoordinateInfo(row, column));
					mediator.playAction();
				}
			}
		}
		
		players = matchManager.getClientPlayer().getCharacters();
		mediator = matchManager.getClientPlayer().getActions();
		// Receive client players (you).
		name = null;
		row = -1;
		column = -1;
		size = players.size();
		
		for(int index = 0; index < size; index++)
		{
			// Name
			name = protocol.receiveMessage();
			// Row
			row = Integer.parseInt(protocol.receiveMessage());
			
			// Column
			column = Integer.parseInt(protocol.receiveMessage());
			for (Character character : players) 
			{
				if(name.equalsIgnoreCase(character.getName()))
				{
					mediator.setAction(StartingPointAction.GUID);
					mediator.addActionInfo(new AddCharacterInfo(character));
					mediator.addActionInfo(new ActionCoordinateInfo(row, column));
					mediator.playAction();
				}
			}
		}
	}

	private void sedingActions(BoomerangProtocol protocol, MatchOnLineManager matchManager) throws UnknownHostException, IOException 
	{
		int index = (matchManager.getStartingPlayerIndex() == MatchManager.CLIENT ? MatchManager.ENEMY : MatchManager.CLIENT);
		protocol.sendMessage(Integer.toString(index));
		
		List<Character> players = matchManager.getClientPlayer().getCharacters();
		// For each players we're going to send his name and his position.
		// Send server players.
		for (Character character : players) 
		{
			protocol.sendMessage(character.getName());
			protocol.sendMessage(Integer.toString(character.getRow()));
			protocol.sendMessage(Integer.toString(character.getColumn()));
		}
		
		// Send remote players.
		players = matchManager.getEnemy().getCharacters();
		for (Character character : players) 
		{
			protocol.sendMessage(character.getName());
			protocol.sendMessage(Integer.toString(character.getRow()));
			protocol.sendMessage(Integer.toString(character.getColumn()));
		}
	}

	/**
	 * @return the map
	 */
	public Map getMap() {
		return map;
	}

	/**
	 * @param map the map to set
	 */
	public void setMap(Map map) 
	{
		this.map = map;
	}

	public void settingUp(MatchOnLineManager molm, OnLineEnemyController oEnemy, SimplePlayer client, BattlePlayer bClient, BoomerangProtocol protocol) throws UnknownHostException, IOException 
	{
		lock.lock();
		try 
		{
			while(mapOff && enemyOff)
			{
				condition.await();
			}
			molm.init(client, oEnemy.getAiPlayer(), bClient, oEnemy.getAiPlayer(), this.map);
			oEnemy.preStartMatch(this.map);
			initMatch(protocol, molm);
			oEnemy.setConnection(protocol);
			Thread t = new Thread(oEnemy);
			t.start();
		} catch (InterruptedException e) 
		{
			e.printStackTrace();
		}
		finally
		{
		lock.unlock();
		}
//		oEnemy.init();
		/*
		 */
	}
	/**
	 * @param mapOff the mapOff to set
	 */
	public void setMapOff(boolean mapOff) 
	{
		lock.lock();
		this.mapOff = mapOff;
		
		if(!mapOff)
			condition.signal();
		lock.unlock();
	}
	/**
	 * @param enemyOff the enemyOff to set
	 */
	public void setEnemyOff(boolean enemyOff) 
	{
		lock.lock();
		this.enemyOff = enemyOff;
		
		if(!enemyOff)
			condition.signal();
		lock.unlock();
	}
	
	
}
